package com.flesler.stickjoy.core.controller;

import net.java.games.input.Component;
import net.java.games.input.Component.Identifier;

public final class ComponentWrapper
{
	private static byte INVALID = 0;
	
	private static byte TRUE = 't';
	private static byte FALSE = 'f';
	private static byte NEGATIVE = 'n';
	private static byte CENTER = 'c';
	private static byte POSITIVE = 'p';
	
	private static float DEAD_ZONE = 0.009f;
	
	private Component component;
	private byte key;
	private byte state;
	private float lastValue;
	
	public ComponentWrapper(Component component)
	{
		this.component = component;
		init();
	}
	
	private byte getDefaultState() {
		if (component.isAnalog())
			return CENTER;
		return FALSE;
	}

	private void init()
	{
		this.key = getKeyFor(component);
		this.state = getDefaultState();
		
		lastValue = 0.0f;
	}
	
	public byte getKey()
	{
		return key;
	}
	
	public byte getState()
	{
		return state;
	}
	
	public boolean isValid()
	{
		return key != INVALID;
	}
	
	private byte getStateFor(float value)
	{
		if (!component.isAnalog())
			return value == 1.0f ? TRUE : FALSE;
		
		if (Math.abs(value) < DEAD_ZONE/*component.getDeadZone()*/)
			return CENTER;
		
		return value < 0 ? NEGATIVE : value > 0 ? POSITIVE : CENTER;
	}
	
	public boolean update(float value)
	{
		if (component.isRelative())
			value += lastValue;
		
		if (value == lastValue)
			return false;
		
		lastValue = value;
		byte newState = getStateFor(value);
		if (state != newState)
		{
			state = newState;
			return true;
		}
		return false;
	}
	
	public void destroy()
	{
		component = null;
	}
	
	// Static
	
	// This is TEMP and needs to be improved
	public static byte getKeyFor(Component component)
	{
		Identifier id = component.getIdentifier();
		byte[] bytes = id.getName().getBytes();
		byte key = bytes[0];
		
		if (isNumber(key))
			return key;
		
		// X or Y axis
		if (id == Component.Identifier.Axis.X || id == Component.Identifier.Axis.Y)
			return key;
		
		return INVALID;
	}
	
	private static boolean isNumber(byte key)
	{
		return key >= '0' && key <= '9';
	}
}
